///////////////////////////////////////////////////////////////////////////////
// Project: Hoyo Client Game
//
// hy_network_message.cpp
// Created: 2012-10-26
// Author: Like Cheng
///////////////////////////////////////////////////////////////////////////////
#include "hy_network_message.h"
#include "msg_base.h"
#include "hy_network_default.h"

#include "hy_player_system/hy_player_logic.h"

#include "game_server.h"
#include "hy_message_dispersed_center.h"

USING_NS_HY_NETWORK;
using namespace hoyosvr;
using namespace hoyosvr::msg;
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
//hy_network_message::hy_network_message
///////////////////////////////////////////////////////////////////////////////
hy_network_message::hy_network_message()
{
	m_player_id = 0;
	m_net_id = 0;
	m_protocol_id = 0;	
	m_msg_type = gen_json_data;
	m_value.clear();
}

hy_network_message::hy_network_message( int msg_type )
{
	m_player_id = 0;
	m_net_id = 0;
	m_protocol_id = 0;	
	m_msg_type = msg_type;
	m_value.clear();

	if( msg_type == gen_stream_data )
	{
// 			m_buf = new schar[MAX_MSG_SIZE];
// 			memset( m_buf, 0 , MAX_MSG_SIZE );
// 			m_max_pos = MAX_MSG_SIZE;
// 			m_cur_pos = 0;
// 			m_error_pos = -1;		
	}
	else if( msg_type == gen_format_stream_data )
	{
		m_string_map = new string_map;
	}
}
///////////////////////////////////////////////////////////////////////////////
//hy_network_message::hy_network_message
///////////////////////////////////////////////////////////////////////////////
hy_network_message::hy_network_message( const char* str, int len )
{
	std::string gstr( str, len );
	msg_base packageHeader( gstr.c_str() );
	m_protocol_id = packageHeader._type;
	m_player_id = packageHeader._player_id;
	m_net_id = packageHeader._net_id;
	m_msg_type = packageHeader._msg_type;

	m_value_str	= std::string( str + msg_offset, packageHeader._total_len-msg_offset );
	switch( packageHeader._msg_type )
	{
	case gen_json_data:
		{
			Json::Reader j_reader;
			if( !j_reader.parse( m_value_str.c_str(), m_value ) )
			{			 
			}
		}
		break;
	}
}
///////////////////////////////////////////////////////////////////////////////
//hy_network_message::~hy_network_message
///////////////////////////////////////////////////////////////////////////////
hy_network_message::~hy_network_message()
{
	if( m_msg_type == gen_stream_data )
	{
		release_buffer();
	}
	else if( m_msg_type == gen_format_stream_data )
	{
		DEL_POINTER( m_string_map );
	}
}

hy_network_message::ptr hy_network_message::create( const char* str, int len )
{
	return ptr( new hy_network_message( str, len ) );
}

int hy_network_message::get_new_pos( int pos )
{
	if( pos == 0 )
	{
		return m_string_map->size()+1;
	}
	else
	{
		return pos + 1000;
	}
}

bool hy_network_message::hy_write_schar( schar c, int pos )
{
	int new_pos = get_new_pos( pos );
	std::stringstream ss;
	ss<<c;
	m_string_map->insert( std::make_pair( new_pos, std::string( ss.str().c_str() ) ) );
	return true;
}
bool hy_network_message::hy_write_uchar( uchar c, int pos )
{
	int new_pos = get_new_pos( pos );
	std::stringstream ss;
	ss<<c;
	m_string_map->insert( std::make_pair( new_pos, std::string( ss.str().c_str() ) ) );
	return true;
}
bool hy_network_message::hy_write_uint16( uint16 c, int pos )
{
	int new_pos = get_new_pos( pos );
	std::stringstream ss;
	ss<<c;
	m_string_map->insert( std::make_pair( new_pos, std::string( ss.str().c_str() ) ) );
	return true;
}
bool hy_network_message::hy_write_sint16( sint16 c, int pos )
{
	int new_pos = get_new_pos( pos );
	std::stringstream ss;
	ss<<c;
	m_string_map->insert( std::make_pair( new_pos, std::string( ss.str().c_str() ) ) );
	return true;
}
bool hy_network_message::hy_write_uint32( uint32 c, int pos )
{
	int new_pos = get_new_pos( pos );
	std::stringstream ss;
	ss<<c;
	m_string_map->insert( std::make_pair( new_pos, std::string( ss.str().c_str() ) ) );
	return true;
}
bool hy_network_message::hy_write_sint( sint c, int pos )
{
	int new_pos = get_new_pos( pos );
	std::stringstream ss;
	ss<<c;
	m_string_map->insert( std::make_pair( new_pos, std::string( ss.str().c_str() ) ) );
	return true;
}
bool hy_network_message::hy_write_float32( float32 c, int pos )
{
	int new_pos = get_new_pos( pos );
	std::stringstream ss;
	ss<<c;
	m_string_map->insert( std::make_pair( new_pos, std::string( ss.str().c_str() ) ) );
	return true;
}
bool hy_network_message::hy_write_uint64( uint64 c, int pos )
{
	int new_pos = get_new_pos( pos );
	std::stringstream ss;
	ss<<c;
	m_string_map->insert( std::make_pair( new_pos, std::string( ss.str().c_str() ) ) );
	return true;
}
bool hy_network_message::hy_write_string( const char *c, int pos )
{
	int new_pos = get_new_pos( pos );
	m_string_map->insert( std::make_pair( new_pos, std::string( c ).c_str() )  );
	return true;
}


///////////////////////////////////////////////////////////////////////////////
//hy_network_message::write_int
///////////////////////////////////////////////////////////////////////////////
void hy_network_message::write_int( int key ,int msg )
{
	std::stringstream ss;
	ss<< key;
	std::string keys = ss.str();
	m_value[keys] = msg;
}
///////////////////////////////////////////////////////////////////////////////
//hy_network_message::write_int
///////////////////////////////////////////////////////////////////////////////
void hy_network_message::write_int( const char *key, int msg )
{
	std::string keys = key;	
	m_value[keys] = msg;
}
///////////////////////////////////////////////////////////////////////////////
//hy_network_message::write_double
///////////////////////////////////////////////////////////////////////////////
void hy_network_message::write_double( int key, double msg )
{
	std::stringstream ss;
	ss<< key;
	std::string keys = ss.str();
	m_value[keys] = msg;
}
///////////////////////////////////////////////////////////////////////////////
//hy_network_message::write_double
///////////////////////////////////////////////////////////////////////////////
void hy_network_message::write_double( const char* key, double msg )
{
	std::string keys = key;	
	m_value[keys] = msg;
}
///////////////////////////////////////////////////////////////////////////////
//hy_network_message::write_msg
///////////////////////////////////////////////////////////////////////////////
void hy_network_message::write_string( int key ,const char* msg )
{
	std::stringstream ss;
	ss<< key;
	std::string keys = ss.str();
	m_value[keys] = msg;
}
///////////////////////////////////////////////////////////////////////////////
//hy_network_message::write_msg
///////////////////////////////////////////////////////////////////////////////
void hy_network_message::write_string( const char* key,const char* msg )
{
	std::string keys = key;
	m_value[keys] = msg;
}
///////////////////////////////////////////////////////////////////////////////
//hy_network_message::write_value
///////////////////////////////////////////////////////////////////////////////
void hy_network_message::write_value( const char* key, Json::Value v )
{
	std::string keys = key;
	m_value[keys] = v;
}
///////////////////////////////////////////////////////////////////////////////
//hy_network_message::read_int
///////////////////////////////////////////////////////////////////////////////
int	hy_network_message::read_int( int key )
{
	std::stringstream ss;
	ss<< key;
	std::string keys = ss.str();
	Json::Value &v = m_value[keys];
	if( !v.empty() ) 
	{
		if( v.isInt() )
			return v.asInt();
	}
	return -1;
}
///////////////////////////////////////////////////////////////////////////////
//hy_network_message::read_int
///////////////////////////////////////////////////////////////////////////////
int	hy_network_message::read_int( const char* key )
{
	std::string keys = key;
	Json::Value &v = m_value[keys];
	if( !v.empty() ) 
	{
		if( v.isInt() )
			return v.asInt();
	}
	return -1;
}
///////////////////////////////////////////////////////////////////////////////
//hy_network_message::read_double
///////////////////////////////////////////////////////////////////////////////
double hy_network_message::read_double( int key )
{
	std::stringstream ss;
	ss<< key;
	std::string keys = ss.str();
	Json::Value &v = m_value[keys];
	if( !v.empty() ) 
	{
		if( v.isDouble() )
			return v.asDouble();
	}
	return -1.0f;
}
///////////////////////////////////////////////////////////////////////////////
//hy_network_message::read_double
///////////////////////////////////////////////////////////////////////////////
double hy_network_message::read_double( const char* key )
{
	std::string keys = key;
	Json::Value &v = m_value[keys];
	if( !v.empty() ) 
	{
		if( v.isDouble() )
			return v.asDouble();
	}
	return -1.0f;
}
///////////////////////////////////////////////////////////////////////////////
//hy_network_message::read_string
///////////////////////////////////////////////////////////////////////////////
std::string	hy_network_message::read_string( int key )
{
	std::stringstream ss;
	ss<< key;
	std::string keys = ss.str();
	Json::Value &v = m_value[keys];
	if( !v.empty() ) 
	{
		if( v.isString() )
			return v.asString();
	}
	return "";
}
///////////////////////////////////////////////////////////////////////////////
//hy_network_message::read_string
///////////////////////////////////////////////////////////////////////////////
std::string	hy_network_message::read_string( const char* key )
{
	std::string keys = key;
	Json::Value &v = m_value[keys];
	if( !v.empty() ) 
	{
		if( v.isString() )
			return v.asString();
	}
	return "";
}
///////////////////////////////////////////////////////////////////////////////
//hy_network_message::read_value
///////////////////////////////////////////////////////////////////////////////
Json::Value hy_network_message::read_value( const char* key )
{
	std::string keys = key;
	Json::Value &v = m_value[keys];
	if( !v.empty() ) 
	{
		return v;
	}
	return Json::Value();
}
///////////////////////////////////////////////////////////////////////////////
//hy_network_message::clear_string
///////////////////////////////////////////////////////////////////////////////
void hy_network_message::clear_string()
{
	m_value_str.clear();
	m_value.clear();
}


std::string hy_network_message::get_head_string()
{
	return "";
}

std::string	hy_network_message::get_content_string()
{
	return "";
}
///////////////////////////////////////////////////////////////////////////////
//hy_network_message::get_string
///////////////////////////////////////////////////////////////////////////////
std::string hy_network_message::get_string()
{
	std::string return_str = hy_message_logic::assembly_message( this->get_player_id(), this->get_net_id(),
		this->get_protocol_id(), *this );

	return return_str;
}

int	hy_network_message::get_total_length()
{
	return 100;
}

////////////////////////////////////////////////////////////////
//hy_network_message::send
////////////////////////////////////////////////////////////////
bool hy_network_message::send()
{
	if( m_player_id )
	{
		m_net_id = hy_player_logic::instance()->get_net_id_by_player_id( m_player_id );
		if( !m_net_id )
			return false;
	}	
	game_server::get_inst()->async_send_to_client( m_net_id, *this );
	return true;
}
////////////////////////////////////////////////////////////////
//hy_network_message::dencrypt_msg
////////////////////////////////////////////////////////////////
std::string hy_network_message::dencrypt_msg(  int count, const char* key, const char * src_data )
{
	if ( key == NULL || src_data == NULL ) return std::string("");

	char * dest_data = new char[count + 1];
	std::string key_str = key;
	int i = 0;
	int keyLen = key_str.length();
	memcpy(dest_data,src_data,count);

	i = count - 1 ;
	while( i >= 0 )
	{
		if ( i < keyLen )
		{
			dest_data[i] = dest_data[i] ^ key_str.at(i);
		}
		else
		{
			dest_data[i] = dest_data[i] ^ dest_data[i-keyLen];
		}
		i--;
	}
	dest_data[count] = '\0';

	std::string dencryptData(dest_data,count);

	delete[] dest_data;
	return dencryptData;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
hy_message_logic* hy_message_logic::instance_p_ = NULL;
///////////////////////////////////////////////////////////////////////////////
//hy_message_logic::hy_message_logic
///////////////////////////////////////////////////////////////////////////////
hy_message_logic::hy_message_logic()
{

}
///////////////////////////////////////////////////////////////////////////////
//hy_message_logic::~hy_message_logic
///////////////////////////////////////////////////////////////////////////////
hy_message_logic::~hy_message_logic()
{

}
///////////////////////////////////////////////////////////////////////////////
//hy_message_logic::instance
///////////////////////////////////////////////////////////////////////////////
hy_message_logic* hy_message_logic::instance()
{
	if( instance_p_ == NULL )
		instance_p_ = new hy_message_logic;
	return instance_p_;
}
///////////////////////////////////////////////////////////////////////////////
//hy_message_logic::assembly_message
///////////////////////////////////////////////////////////////////////////////
std::string hy_message_logic::assembly_message( uint player_id, uint net_id, uint protocol_id, hy_network_message &msg )
{
	Json::Value &json_value = msg.get_value();

	std::string style_str = "";
	if( msg.get_msg_type() == gen_json_data )
	{
		style_str = json_value.toStyledString();
	}
	else if( msg.get_msg_type() == gen_stream_data )
	{
		style_str = msg.get_buffer();
	}
	else if( msg.get_msg_type() == gen_format_stream_data )
	{
		string_map* sm = msg.get_string_map();
		if( !sm )return "";

		std::stringstream ss;
		string_map::iterator it, next_it;
		for( it = sm->begin(); it != sm->end(); it++ )
		{
			ss<< it->first << ':' << it->second.c_str();
			next_it = it;
			advance( next_it, 1 );
			if( next_it != sm->end() )
			{
				ss<< '|';
			}
		}
		style_str = ss.str().c_str();
	}
	
	
	msg_base base;
	size_t size_data = sizeof( base );
	base._net_id = net_id;
	base._player_id = player_id;
	base._type = protocol_id;
	base._msg_type = msg.get_msg_type();
	base._total_len = style_str.size() + size_data;

	char dest[msg_offset];	
	memcpy( dest, &base, size_data );	
	stringstream aa;
	for ( int i = 0; i < msg_offset; ++i )
	{
		aa<<dest[i];
	}	
	std::string str__ = aa.str();
	std::string string_end = str__ + style_str;
	return string_end;
	
	return "";
}
///////////////////////////////////////////////////////////////////////////////
//hy_message_logic::process_message
///////////////////////////////////////////////////////////////////////////////
bool hy_message_logic::process_message( const char* c, int l )
{	
	/*
	bool flag = true;

	int len = l;
	hy_stream stream;
	stream.set_buffer( c, len );
	m_buffer.clear();

	int flag_len = 0;
	while( flag )
	{
		if( len == 0 )
			return false;
		if( len < 14 )
			return false;
		
		int totle_len = stream.read_sint();
		short protocol_id = stream.read_uint16();
		int net_id = stream.read_sint();
		int player_id = stream.read_sint();

		std::string json_value = stream.get_buffer_by_pos( flag_len + 14, flag_len + totle_len );
		Json::Reader j_reader;
		Json::Value root_value;
		if( !j_reader.parse( json_value.c_str(), root_value ) )
		{
			return false;
		}

		hy_network_message *msg = new hy_network_message;
		msg->set_value( root_value );
		msg->set_player_id( player_id );
		msg->set_net_id( net_id );
		msg->set_protocol_id( protocol_id );

		std::string get_style = msg->get_value().toStyledString();

		m_buffer.push_back( msg );

		if( len == flag_len + totle_len )
		{
			flag = false;
		}
		flag_len += totle_len;
		stream.set_cur_pos( flag_len );
	}
	
	hy_network_message_vec::iterator it;

	for( it = m_buffer.begin(); it != m_buffer.end(); it++ )
	{
		hy_network_message* newmsg = *it;
		hy_message_dispersed_center::instance()->message_dispersed( newmsg );
		DEL_POINTER( newmsg );
	}
	m_buffer.clear();
	*/

	return true;
}